use std::fmt;
use std::marker;
use std::io::{Result,ErrorKind,Error};

use super::ukey::Ukey;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct GP {
    pub id: Ukey,
    pub offset: u64,
    pub size: u64,
}

impl fmt::Display for GP {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "id:{} offset: {:?} size: {:?}",
            self.id,
            self.offset,
            self.size
        )
    }
}

impl Default for GP {
    fn default() -> Self {
        return GP {
            id: Ukey::default(),
            offset: 0,
            size: 0,
        };
    }
}

#[repr(C)]
pub struct GTP<T> {
    pub gp:GP,
    _marker:marker::PhantomData<T>,
}

impl<T> fmt::Display for GTP<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}({})",
            std::any::type_name::<T>(),
            self.gp
        )
    }
}

impl<T> Default for GTP<T> {
    fn default() -> Self {
        let s = std::mem::size_of::<T>();
        GTP::<T>{gp:GP{ id: Ukey::default(),offset: 0,size: s as u64}
        ,_marker:marker::PhantomData::default()}
    }
}

impl<T> GTP<T> {
    
    pub fn from_gp(gp :&GP) -> Result<GTP<T>> {
        if std::mem::size_of::<T>() == gp.size as usize {
            Ok(GTP::<T>{gp:*gp,_marker:marker::PhantomData::default()})
        } else {
            Err(Error::new(ErrorKind::Other,"size miss match"))
        }
    }
    pub fn as_gp(&self) -> &GP { &self.gp }
}